﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace OpenPasteSpider
{
    /// <summary>
    /// 基于IAuthorizationFilter
    /// </summary>
    public class RoleAttribute : IAsyncAuthorizationFilter
    {

        /// <summary>
        /// 权限
        /// </summary>
        private string _role { set; get; }

        /// <summary>
        /// 角色
        /// </summary>
        private string _model { get; set; }

        /// <summary>
        /// 
        /// </summary>
        private readonly SpiderConfig _config;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="config"></param>
        /// <param name="model"></param>
        /// <param name="role"></param>
        public RoleAttribute(
            IOptions<SpiderConfig> config,
            string model = "",
            string role = "")
        {
            _config = config.Value;
            _model = model;
            _role = role;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            var needauth = true;
            foreach (var item in context.Filters)
            {
                if (item is RoleAttribute)
                {
                    needauth = (item == this);
                }
            }
            //是否支持混合模式 会员模式 管理员模式 维修站模式 ？？？
            // 
            if (needauth)
            {

                var _action = String.Empty;
                var _controller = String.Empty;
                //这里还可以解析出其他信息 比如site_id 
                foreach (var ii in context.RouteData.Values)
                {
                    if (ii.Key == "action")
                    {
                        _action = ii.Value.ToString();
                    }
                    if (ii.Key == "controller")
                    {
                        _controller = ii.Value.ToString();
                    }
                }

                if (String.IsNullOrEmpty(_model))
                {
                    _model = _controller;
                }
                if (String.IsNullOrEmpty(_role))
                {
                    _role = _action;
                }
                //root-root 所有权限
                //xxx-root 有这个xxx的controller的所有权限
                //角色 模块 权限 灵活授权方式 整个系统中角色不能过多，或者说一个账号不能授权过多角色
                //Console.WriteLine("PathBase:{0},Path:{1}",context.HttpContext.Request.PathBase,context.HttpContext.Request.Path);

                var token = String.Empty;
                if (context.HttpContext.Request.Headers.ContainsKey("token"))
                {
                    token = context.HttpContext.Request.Headers["token"].ToString();
                }
                else
                {
                    if (context.HttpContext.Request.Cookies.ContainsKey("token"))
                    {
                        context.HttpContext.Request.Cookies.TryGetValue("token", out token);
                    }
                }

                //1747125851__574305cd-d10f-0f61-f9f5-3a19dafa594e__root_ff984dd1bb8aa240973291d0c09d44dd

                var auth_throw_code = 401;//是否需要触发401错误
                if (!String.IsNullOrEmpty(token))
                {
                    if (token.StartsWith("Bearer"))
                    {
                        token = token.Replace("Bearer ", "");
                    }
                    if (token.CheckToken(_config.UserToken))
                    {
                        //这个主要是给后续的 权限判断使用 在上面
                        auth_throw_code = 200;
                    }
                    else
                    {
                        auth_throw_code = 401;
                        await Task.Delay(100);
                    }
                }

                if (auth_throw_code == 401 || auth_throw_code == 403)
                {
                    var info = new ErrorInfoModel();
                    info.code = auth_throw_code.ToString();
                    info.success = false;
                    info.message = $"当前密钥信息有误，请登陆后重试! {token}";
                    context.Result = new ContentResult
                    {
                        StatusCode = auth_throw_code,
                        ContentType = "application/json;charset=utf-8",
                        Content = Newtonsoft.Json.JsonConvert.SerializeObject(info)
                    };
                }
            }
        }
    }


    /// <summary>
    /// 自定义全局错误处理，使用错误代码httpstatuscode
    /// </summary>
    public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
    {

        private readonly ILogger<CustomExceptionFilterAttribute> _logger;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="logger"></param>
        public CustomExceptionFilterAttribute(ILogger<CustomExceptionFilterAttribute> logger)
        {
            _logger = logger;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public override void OnException(ExceptionContext context)
        {

            // 如果异常没有被处理则进行处理
            if (context.ExceptionHandled == false)
            {
                var userExpect = (context.Exception.InnerException != null ? context.Exception.InnerException : context.Exception) as Volo.Abp.UserFriendlyException;
                var info = new ErrorInfoModel();
                //info.error = new ErrorInfoModel();
                info.code = "500";
                info.success = false;
                info.message = "服务器遇到一个错误，无法继续为您服务!";

                if (userExpect != null)
                {
                    if (!String.IsNullOrEmpty(userExpect.Code))
                    {
                        info.code = userExpect.Code;
                    }
                    else
                    {
                        info.code = "502";
                    }
                    info.message = context.Exception.Message;
                }
                else
                {
                    var volexception = context.Exception as PasteCodeException;
                    if (volexception != null)
                    {
                        info.code = volexception.Code.ToString();
                        info.message = volexception.Message;
                    }
                    else
                    {
                        var exception = context.Exception.InnerException != null ? context.Exception.InnerException : context.Exception;
                        if (exception != null)
                        {
                            info.code = "500";
                            info.message = exception.Message;
                        }

                    }
                }

                if (context.ModelState != null)
                {
                    if (context.ModelState.Count > 0)
                    {
                        foreach (var key in context.ModelState.Keys)
                        {
                            context.ModelState.TryGetValue(key, out var val);
                            if (val.Errors.Count > 0)
                            {
                                info.message = key + "::" + val.Errors[0].ErrorMessage;
                                info.code = "400";
                                break;
                            }
                        }
                    }
                }

                if (!String.IsNullOrEmpty(info.code) && info.code == "500")
                {
                    //写入日志
                    _logger.LogError(context.Exception, context.HttpContext.Request.Path, null);
                }

                context.Result = new ContentResult
                {
                    // 返回状态码设置为200，表示成功
                    StatusCode = int.Parse(info.code),
                    // 设置返回格式
                    ContentType = "application/json;charset=utf-8",
                    Content = Newtonsoft.Json.JsonConvert.SerializeObject(info)
                };
            }
            // 设置为true，表示异常已经被处理了
            context.ExceptionHandled = true;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override System.Threading.Tasks.Task OnExceptionAsync(ExceptionContext context)
        {
            return base.OnExceptionAsync(context);
        }
    }

}
